package com.tcs.redis.aop;

import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.concurrent.TimeUnit;

import javax.annotation.Resource;

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;

import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.tcs.redis.annotations.RedisCache;

import redis.clients.jedis.JedisCluster;

/**
 * Redis 注解
* @Title: RedisAop.java
* @Package com.tcs.redis.aop
* @author 神经刀
* @date 2018年6月13日
* @version V1.0
 */
@Aspect
public class RedisAop {
	
	@Resource(name="jedisCluster")
	private JedisCluster jedisCluster;

	@Pointcut("execution(* com.tcs..*.*(..))")
    public void pointcutName(){}
	
	@Around("pointcutName()")
    public Object processTx(ProceedingJoinPoint jp) throws Throwable {
		Object resultObj = null;
		ObjectMapper mapper = new ObjectMapper();
    	MethodSignature methodSignature = (MethodSignature)jp.getSignature();
		Method targetMethod = methodSignature.getMethod();
		
		if (targetMethod.isAnnotationPresent((RedisCache.class))) {
			String key = jp.getTarget().getClass().getName() + targetMethod.getName() + Arrays.toString(jp.getArgs());
			RedisCache redisCache = (RedisCache)targetMethod.getAnnotation(RedisCache.class);
			if (jedisCluster.exists(key)) {
				mapper.configure(DeserializationFeature.ACCEPT_SINGLE_VALUE_AS_ARRAY, true);
				resultObj = mapper.readValue(jedisCluster.get(key).toString(),targetMethod.getReturnType());
			} else {
				resultObj = jp.proceed();
				long saveTime = redisCache.saveTime();
				saveTime = TimeUnit.MILLISECONDS.convert(saveTime, redisCache.timeUnit());
				mapper.setSerializationInclusion(JsonInclude.Include.NON_EMPTY);
				if (0 == saveTime) {
					jedisCluster.set(key, mapper.writeValueAsString(resultObj));
				} else {
					jedisCluster.psetex(key, saveTime, mapper.writeValueAsString(resultObj));
				}
			}
		} else {
			resultObj = jp.proceed();
		}
		return resultObj;
    }
}
